<template>
    <a-popover v-bind="$attrs" trigger="click" class="color-picker" :visible="showPicker"
        :getPopupContainer="getPopupContainer" :class="[colorSize ? 'color-picker--' + colorSize : '']">
        <template #content>
            <div class="color-dropdown__main-wrapper">
                <SvPanel ref="svPanel" :color="color" />
                <HueSlider ref="hue" class="hue-slider" :color="color" vertical />
            </div>
            <AlphaSlider v-show="props.showAlpha" ref="alpha" :color="color" />
            <preDefine v-show="predefine.length" ref="predefine" :color="color" :colors="predefine" />
            <div class="color-dropdown__btns">
                <span class="color-dropdown__value">
                    <a-input v-model:value="customInput" size="small" @pressEnter="handleConfirm" @blur="handleConfirm" />
                </span>
                <div class="dropdown__btns">
                    <a-button size="small" class="cancel-button" @click="clear">取消</a-button>
                    <a-button type="primary" size="small" @click="confirmValue">确定</a-button>
                </div>
            </div>
        </template>
        <span class="color-picker__trigger" @click="handleTrigger">
            <span class="color-picker__color" :class="{ 'is-alpha': showAlpha }">
                <span class="color-picker__color-inner" :style="{
                    backgroundColor: color.value
                }">
                    <DownOutlined v-show="value || showPanelColor" style="color: #909399" />
                    <CloseOutlined v-if="!value && !showPanelColor" style="color: #909399" />
                </span>
            </span>
        </span>
    </a-popover>
</template>
<script setup lang="ts">
import AlphaSlider from "./components/alpha-slider.vue";
import HueSlider from "./components/hue-slider.vue";
import SvPanel from "./components/sv-panel.vue";
import preDefine from "./components/pre-define.vue";
import { CloseOutlined, DownOutlined } from '@ant-design/icons-vue';
import { IEvent } from '@/core';
import debounce from 'lodash/debounce';
import Color from './util/color';
import { IUseOptions, OPTIONS_KEY, ColorPickerProps } from './color-picker';

type eventType = 'valueChange' | 'activeChange' ;

interface EditorEmit {
	(name: 'component-action', value: IEvent<eventType>): void;
}
const props = defineProps(ColorPickerProps);
const emit = defineEmits<EditorEmit>();
/**
 * popover 显示状态
 */
let showPicker = ref(false);
/**
 * setShowPicker事件
 * @param value
 */
 const setShowPicker = (value: any) =>  {
    showPicker.value = value
}
const debounceSetShowPicker = debounce(setShowPicker, 50)
/**
 * 区分popover的关闭是通过点击body关闭的还是通过按钮、输入框关闭的
 */
const hasClickBtn = ref<boolean>(false)
const showAlpha = ref<boolean>(true) //管理透明度条
const hue = ref<any>(null) //管理HueSlider
const svPanel = ref<any>(null) //管理SvPanel
const alpha = ref<any>(null) //管理AlphaSlider
const showPanelColor = ref(false) //管理显示面板
const customInput = ref<any>('')  //定义输入框


/**
* new Color
*/
const color: Color = reactive(
    new Color({
        enableAlpha: props.showAlpha,
        format: props.showAlpha ? 'rgb' : props.colorFormat
    })
)

/**
* 选择器大小
*/
const colorSize = computed(() => {
    return props.size
})

/**
* 选择器启动
*/
const colorDisabled = computed(() => {
    return props.disabled
})

/**
* 计算当前颜色的#十六进制值
*/
const currentColor = computed(() => {
    return !props.value && !showPanelColor.value ? '' : color.value
})

/**
* 监听value值
*/
watch(
    () => props.value,
    (newVal: string) => {
        if (!newVal) {
            showPanelColor.value = false
        } else if (newVal && newVal !== color.value) {
            color.fromString(newVal)
        }
    }
)

/**
* 监听转换后的十六进制值
*/
watch(
    () => currentColor.value,
    (val: string) => {
        customInput.value = val
        doEditorEmit('activeChange', val);
    }
)
/**
* 监听颜色值
*/
watch(
    () => color.value,
    () => {
        if (!props.value && !showPanelColor.value) {
            showPanelColor.value = true
        }
    })

/**
* 监听选择器控制值
*/
watch(
    () => showPicker.value,
    (newVal: boolean) => {
        if (newVal) {
            hasClickBtn.value = false
        } else {
            if (!hasClickBtn.value) {
                hide()
            }
        }
        setTimeout(() => {
            hue.value?.update()
            svPanel.value?.update()
            alpha.value?.update()
        }, 100);
    }
)

/**
 * hide事件
 */
const hide = () => {
    debounceSetShowPicker(false)
    resetColor()
}

/**
* resetColor事件
*/
const resetColor = () => {
    nextTick(() => {
        if (props.value) {
            color.fromString(props.value)
        } else {
            showPanelColor.value = false
        }
    })
}

/**
* handleTrigger触发事件
*/
const handleTrigger = () => {
    if (colorDisabled.value) return
    debounceSetShowPicker(!showPicker.value)
}

/**
* 失去焦点确认事件
*/
const handleConfirm = () => {
    color.fromString(customInput.value)
}

/**
* 确定值
*/
const confirmValue = () => {
    hasClickBtn.value = true
    const colorValue = color.value
    doEditorEmit('valueChange', colorValue);
    debounceSetShowPicker(false)
    nextTick(() => {
        const newColor = new Color({
            enableAlpha: props.showAlpha,
            format: props.showAlpha ? 'rgb' : props.colorFormat
        })
        newColor.fromString(props.value)
        if (!color.compare(newColor)) {
            resetColor()
        }
    })
    showPicker.value = false
    return colorValue
}

/**
* 取消(清除)值
*/
const clear = () => {
    color.value = ''
    hasClickBtn.value = true
    debounceSetShowPicker(false)
    resetColor()
    showAlpha.value = false
    showPicker.value = false
}

/**
* 获取popover容器
*/
const getPopupContainer = (triggerNode: HTMLElement) => {
    return triggerNode.parentElement
}

/**
* 处理编辑器抛值
*/
const doEditorEmit = (action: eventType, value: any) => {
    emit('component-action', {
        name: props.name,
        action: action,
        data: value
    });
};

onMounted(() => {
    clear()
    if (props.value) {
        color.fromString(props.value)
        customInput.value = currentColor.value
    }
})

provide<IUseOptions>(OPTIONS_KEY, {
    currentColor
})
</script>

